﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Web;

namespace ImpressionPrint.Utility
{
    public class HttpHelper
    {
        #region 变量定义
        private CookieContainer cc = new CookieContainer();
        private string contentType = "application/x-www-form-urlencoded";
        private string accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
        private string userAgent = "Mozilla/5.0 (Windows NT 6.1; rv:2.0) Gecko/20100101 Firefox/4.0";
        private Encoding encoding = Encoding.GetEncoding("utf-8");
        private int delay = 1000;
        private int maxTry = 300;
        private int currentTry = 0;
        public IWebProxy Proxy;
        #endregion

        #region 变量赋值
        /// <summary> 
        /// Cookie
        /// </summary> 
        public CookieContainer CookieContainer
        {
            get
            {
                return cc;
            }
        }

        /// <summary> 
        /// 语言
        /// </summary> 
        /// <value></value> 
        public Encoding Encoding
        {
            get
            {
                return encoding;
            }
            set
            {
                encoding = value;
            }
        }

        public int NetworkDelay
        {
            get
            {
                Random r = new Random();
                return (r.Next(delay, delay * 2));
            }
            set
            {
                delay = value;
            }
        }

        public int MaxTry
        {
            get
            {
                return maxTry;
            }
            set
            {
                maxTry = value;
            }
        }
        #endregion

        #region 获取HTML
        /// <summary>
        /// 获取HTML
        /// </summary>
        /// <param name="url">地址</param>
        /// <param name="postData">post 提交的字符串</param>
        /// <param name="isPost">是否是post</param>
        /// <param name="cookieContainer">CookieContainer</param>
        /// <returns>html </returns>
        public string GetHtml(string url, string postData, bool isPost, CookieContainer cookieContainer, string refurl, bool findHttpOlnyCookie)
        {
            ServicePointManager.Expect100Continue = false;
            if (string.IsNullOrEmpty(postData))
            {
                return GetHtml(url, cookieContainer);
            }

            //Thread.Sleep(NetworkDelay);//等待

            currentTry++;

            HttpWebRequest httpWebRequest = null;

            HttpWebResponse httpWebResponse = null;
            try
            {
                byte[] byteRequest = Encoding.Default.GetBytes(postData);

                httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url);
                if (Proxy != null)
                    httpWebRequest.Proxy = Proxy;
                httpWebRequest.CookieContainer = cookieContainer;
                httpWebRequest.ContentType = contentType;
                httpWebRequest.ServicePoint.ConnectionLimit = maxTry;
                httpWebRequest.Referer = refurl;
                httpWebRequest.Accept = accept;
                httpWebRequest.UserAgent = userAgent;
                httpWebRequest.Method = isPost ? "POST" : "GET";
                httpWebRequest.ContentLength = byteRequest.Length;

                Stream stream = httpWebRequest.GetRequestStream();
                stream.Write(byteRequest, 0, byteRequest.Length);
                stream.Close();

                httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
                Stream responseStream = httpWebResponse.GetResponseStream();
                StreamReader streamReader = new StreamReader(responseStream, encoding);
                string html = streamReader.ReadToEnd();
                streamReader.Close();
                responseStream.Close();
                currentTry = 0;

                httpWebRequest.Abort();
                httpWebResponse.Close();
                foreach (Cookie cookie in httpWebResponse.Cookies)
                {
                    cookieContainer.Add(cookie);
                }

                if (findHttpOlnyCookie)
                {
                    string setCookie = httpWebResponse.Headers[HttpResponseHeader.SetCookie];
                    if (!string.IsNullOrEmpty(setCookie))
                    {
                        string[] tmp = setCookie.Split(new string[] { ";", "=" }, StringSplitOptions.RemoveEmptyEntries);
                        Cookie cookie = new Cookie(tmp[0], tmp[1], tmp[5], tmp[3]);
                        //cookie.Expires =Convert.ToDateTime ( tmp[7]);
                        cookieContainer.Add(cookie);
                    }
                }

                return html;
            }
            catch (Exception e)
            {
                //Console.ForegroundColor = ConsoleColor.Red;
                //Console.WriteLine(DateTime.Now.ToString("HH:mm:ss ") + e.Message);
                //Console.ForegroundColor = ConsoleColor.White;

                //if (currentTry <= maxTry)
                //{
                //    GetHtml(url, postData, isPost, cookieContainer);
                //}
                //currentTry--;

                if (httpWebRequest != null)
                {
                    httpWebRequest.Abort();
                } if (httpWebResponse != null)
                {
                    httpWebResponse.Close();
                }
                return "";
            }
        }
        /// <summary>
        /// 获取HTML
        /// </summary>
        /// <param name="url">地址</param>
        /// <param name="cookieContainer">CookieContainer</param>
        /// <returns>HTML</returns>
        public string GetHtml(string url, CookieContainer cookieContainer)
        {
            return GetHtml(url, cookieContainer, url, false);
        }

        public string GetHtml(string url, CookieContainer cookieContainer, bool findHttpOlnyCookie)
        {
            return GetHtml(url, cookieContainer, url, findHttpOlnyCookie);
        }

        public string GetHtml(string url, CookieContainer cookieContainer, string refUrl, bool findHttpOlnyCookie)
        {
            Thread.Sleep(NetworkDelay);

            currentTry++;
            HttpWebRequest httpWebRequest = null;
            HttpWebResponse httpWebResponse = null;
            try
            {

                httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url);
                if (Proxy != null)
                    httpWebRequest.Proxy = Proxy;
                httpWebRequest.CookieContainer = cookieContainer;
                // httpWebRequest.ContentType = contentType;
                httpWebRequest.ServicePoint.ConnectionLimit = maxTry;
                httpWebRequest.Referer = refUrl;
                httpWebRequest.Accept = accept;
                httpWebRequest.UserAgent = userAgent;
                httpWebRequest.Method = "GET";

                httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
                Stream responseStream = httpWebResponse.GetResponseStream();
                StreamReader streamReader = new StreamReader(responseStream, encoding);
                string html = streamReader.ReadToEnd();
                streamReader.Close();
                responseStream.Close();

                //currentTry--;

                //httpWebRequest.Abort();
                //httpWebResponse.Close();



                foreach (Cookie cookie in httpWebResponse.Cookies)
                {
                    cookieContainer.Add(cookie);
                }

                if (findHttpOlnyCookie)
                {
                    //string setCookie=httpWebResponse.Headers[ HttpResponseHeader.SetCookie];
                    //if (!string.IsNullOrEmpty(setCookie))
                    //{
                    //    string [] tmp=setCookie.Split (new string []{";","="}, StringSplitOptions.RemoveEmptyEntries );
                    //    Cookie cookie = new Cookie(tmp[0], tmp[1],tmp[5], tmp[3]);
                    //    //cookie.Expires =Convert.ToDateTime ( tmp[7]);
                    //    cookieContainer.Add(cookie);
                    //}
                }


                return html;
            }
            catch (Exception e)
            {
                //Console.ForegroundColor = ConsoleColor.Red;
                //Console.WriteLine(DateTime.Now.ToString("HH:mm:ss ") + e.Message);
                //Console.ForegroundColor = ConsoleColor.White;

                //if (currentTry <= maxTry)
                //{
                //    GetHtml(url, cookieContainer);
                //}

                //currentTry--;

                if (httpWebRequest != null)
                {
                    httpWebRequest.Abort();
                } if (httpWebResponse != null)
                {
                    httpWebResponse.Close();
                }
                return "";
            }
        }

        /// <summary>
        /// 获取HTML
        /// </summary>
        /// <param name="url">地址</param>
        /// <returns>HTML</returns>
        public string GetHtml(string url)
        {
            return GetHtml(url, cc);
        }
        /// <summary>
        /// 获取HTML
        /// </summary>
        /// <param name="url">地址</param>
        /// <param name="postData">提交的字符串</param>
        /// <param name="isPost">是否是POST</param>
        /// <returns>HTML</returns>
        public string GetHtml(string url, string postData, bool isPost)
        {
            return GetHtml(url, postData, isPost, cc, url, false);
        }
        /// <summary>
        /// 获取字符流
        /// </summary>
        /// <param name="url">地址</param>
        /// <param name="cookieContainer">cookieContainer</param>
        /// <returns>Stream</returns>
        public Stream GetStream(string url, CookieContainer cookieContainer)
        {
            //Thread.Sleep(delay); 

            currentTry++;
            HttpWebRequest httpWebRequest = null;

            HttpWebResponse httpWebResponse = null;

            try
            {

                httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url);
                if (Proxy != null)
                    httpWebRequest.Proxy = Proxy;
                httpWebRequest.CookieContainer = cookieContainer;
                httpWebRequest.ContentType = contentType;
                httpWebRequest.ServicePoint.ConnectionLimit = maxTry;
                httpWebRequest.Referer = url;
                httpWebRequest.Accept = accept;
                httpWebRequest.UserAgent = userAgent;
                httpWebRequest.Method = "GET";

                httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
                Stream responseStream = httpWebResponse.GetResponseStream();
                currentTry--;
                //httpWebRequest.Abort(); 
                //httpWebResponse.Close(); 
                foreach (Cookie cookie in httpWebResponse.Cookies)
                {
                    cookieContainer.Add(cookie);
                }

                return responseStream;
            }
            catch (Exception e)
            {
                //Console.ForegroundColor = ConsoleColor.Red;
                //Console.WriteLine(DateTime.Now.ToString("HH:mm:ss ") + e.Message);
                //Console.ForegroundColor = ConsoleColor.White;

                //if (currentTry <= maxTry)
                //{
                //    GetHtml(url, cookieContainer);
                //}

                //currentTry--;

                if (httpWebRequest != null)
                {
                    httpWebRequest.Abort();
                } if (httpWebResponse != null)
                {
                    httpWebResponse.Close();
                }
                return null;
            }
        }



        #endregion

        /// <summary>
        /// 获取cookie参数
        /// </summary>
        /// <param name="cc">cookie集合</param>
        /// <returns></returns>
        public static string GetGtkByCookieSkey(string key, CookieContainer cc)
        {
            Hashtable table = (Hashtable)cc.GetType().InvokeMember("m_domainTable", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Instance, null, cc, new object[] { });
            foreach (object pathList in table.Values)
            {
                SortedList lstCookieCol = (SortedList)pathList.GetType().InvokeMember("m_list", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Instance, null, pathList, new object[] { });
                foreach (CookieCollection colCookies in lstCookieCol.Values)
                    foreach (Cookie c in colCookies)
                    {
                        if (c.Name.ToLower() == key)
                        {
                            return c.Value;
                        }
                    }
            }
            return "";
        }

        public T post<T>(string serviceurl, string cmd, object para) where T : InvokeResult, new()
        {

            T result = default(T);
            string url = string.Format("{0}/{1}", serviceurl, cmd);
            string postdata = "data=" + HttpUtility.UrlEncode(JsonHelper.SerializeObject(para));
            string html = GetHtml(url, postdata, true);
            if (string.IsNullOrEmpty(html))
            {
                result = new T();
                result.msg = "连接服务器失败.";
            }
            else
            {
                try
                {
                    result = JsonHelper.DeserializeObject<T>(html);
                }
                catch (Exception ex)
                {

                    result = new T();
                    result.msg = "服务器返回的数据无法识别!";
                }
            }

            return result;
        }

    }
}